/*
 * Design Assignment 5
 *
 * Created: 2014/3/31 1:24:01
 *  Author: Rong Xue
 */ 

#define  F_CPU 8000000UL //8Mhz
#define  UBRR_9600 51 //8Mhz with .2% error
#include <util/delay.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <avr/io.h>

void usart_init(unsigned ubrr)
// initialize the USART interface
{
	UCSR0B=(1<<TXEN0); //enable receiver, transmitter and interrupt
	UCSR0C=(3<<UCSZ00); //Set frame format
	UBRR0H=(unsigned char)(ubrr>>8); //shift right 8 times
	UBRR0L=(unsigned char)ubrr; // lower byte
}

void usart_send(unsigned char ch)
// send data to port
{
	while(!(UCSR0A&(1<<UDRE0)));//check UDREE
	UDR0=ch;	// send to buffer
}
void usart_disp(char* tmp)
// send data to port 
{
	while((*tmp!=0x00))
	{
		usart_send(*tmp);
		tmp++; 
	}
}
void segdisp(unsigned char cmd, unsigned char data)
{
	PORTB &=~(1<<PB2); // initializing the packet
	SPDR=cmd; //start CMD transmission
	while(!(SPDR & (1<<SPIF)));//wait transfer finish
	SPDR = data; //start DATA transmission
	while (!(SPSR & (1<<SPIF))); //wait transfer finish
	PORTB |=(1<<PB2);//terminate the packet
	
}
void tdisplay(int temp)
// function display the temperature to the serial 
{
	char disp[50]; //declare disp with 50 chara length
	snprintf(disp,50,"Right now is %d.%dF.\n",temp/10,temp%10); // print temperature
	usart_disp(disp);	// call send data function
	//_delay_ms(1000);
}

int main(void)
{
    DDRC =0x00; //set PDC for ADC output
	ADCSRA =0x8f; // enable ADC with prescaler 128
	ADMUX =0xc0;
	
	TCCR1A=0x00; // start CTC mode
	TCCR1B=0x0C; // set prescaler 256
	OCR1AH=0x7A;
	OCR1AL=0x11; // 1 sec delay = 0x7A11
	TIMSK1=(1<<OCIE1A); 
	 
	usart_init(UBRR_9600); //initialize the usart interface
	usart_disp("The Temperature is:\r\n"); //print the first message
	
	DDRB|=(1<<PB2)|(1<<PB3)|(1<<PB5); // set Port b2,b3,b5 as output 
	SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR0); //enable SPI as master
	segdisp(0x09,0b00001111); //enable decoding for digits 1,2,3,4
	segdisp(0x0B,0x04); //scan 7-seg
	segdisp(0x0C,0x01); // turn on the chip
	sei(); // enable interrupt
	while(1);
	return 0;
   
}

ISR(ADC_vect)
{
	uint8_t ADC_value_L=ADCL; 
	uint16_t ADC_value=(ADCH<<8)|ADC_value_L; //get value from the temp sensor
	
	// display the temp value on the 7-seg 
	segdisp(0x01,ADC_value%10);  
	segdisp(0x02,ADC_value%100/10|(1<<7)); //(1<<7) represent the decimal points
	segdisp(0x03,ADC_value%1000/100);
	segdisp(0x04,ADC_value/1000);
	
	tdisplay(ADC_value); // display temperature on serial terminal
}

ISR(TIMER1_COMPA_vect)
{
	ADCSRA|=(1<<ADSC);
}